import unittest
import os
import json
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from search_manager import SearchManager
from data_manager import DataManager

class TestSearchAccuracy(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        """测试类初始化，创建必要的测试数据"""
        cls.data_manager = DataManager()
        cls.search_manager = SearchManager(cls.data_manager)
        
        # 确保测试前缓存是空的
        cls.search_manager.clear_cache()
        
        # 加载所有测试数据文件
        cls.all_files = [f for f in os.listdir(cls.data_manager.data_dir) if f.endswith('.json')]
        cls.test_data = {}
        for file in cls.all_files:
            try:
                with open(cls.data_manager.get_data_path(file), 'r', encoding='utf-8') as f:
                    cls.test_data[file] = json.load(f)
            except Exception as e:
                print(f"加载测试数据失败: {file}, {str(e)}")
                
    def setUp(self):
        """每个测试用例前清理缓存"""
        self.search_manager.clear_cache()
        
    def test_search_completeness(self):
        """测试搜索结果的完整性，检查是否有漏项
        
        测试策略：
        1. 对每个测试关键词：
           - 在所有字段中查找包含该关键词的文件
           - 执行搜索并获取结果
           - 比对预期结果和实际结果
        2. 详细记录每个匹配的位置和原因
        3. 对任何差异进行深入分析
        """
        test_words = ["的", "测试", "功能", "python", "代码"]  # 增加测试关键词
        fields_to_check = ['name', 'content', 'comment', 'group']
        
        def find_keyword_in_file(file_data, keyword):
            """在单个文件的所有字段中查找关键词
            返回: (是否找到, 包含关键词的字段列表)
            """
            found_fields = []
            for field in fields_to_check:
                field_value = str(file_data.get(field, '')).lower()
                if keyword.lower() in field_value:
                    found_fields.append(field)
            return bool(found_fields), found_fields
            
        def analyze_search_results(keyword):
            """分析单个关键词的搜索结果
            返回: (漏项文件列表, 多余文件列表, 详细信息字典)
            """
            # 执行搜索并获取结果
            search_results = self.search_manager.global_search(keyword)
            result_files = {result[0] for result in search_results}
            
            # 预期应该匹配的文件
            expected_matches = {}  # 文件名 -> 匹配字段列表
            for file, data in self.test_data.items():
                found, fields = find_keyword_in_file(data, keyword)
                if found:
                    expected_matches[file] = fields
                    
            # 找出漏项和多余项
            expected_files = set(expected_matches.keys())
            missing_files = expected_files - result_files
            extra_files = result_files - expected_files
            
            # 收集详细信息
            details = {
                'total_expected': len(expected_files),
                'total_found': len(result_files),
                'missing_count': len(missing_files),
                'extra_count': len(extra_files),
                'expected_matches': expected_matches
            }
            
            return missing_files, extra_files, details
            
        # 执行测试
        all_tests_passed = True
        test_results = {}
        
        print("\n搜索完整性测试开始...")
        for keyword in test_words:
            print(f"\n测试关键词 '{keyword}':")
            missing, extra, details = analyze_search_results(keyword)
            
            # 记录测试结果
            test_results[keyword] = {
                'missing': missing,
                'extra': extra,
                'details': details
            }
            
            # 输出详细信息
            print(f"  预期匹配: {details['total_expected']} 个文件")
            print(f"  实际找到: {details['total_found']} 个文件")
            
            if missing:
                print("\n  遗漏的文件:")
                for file in missing:
                    print(f"    - {file}")
                    print(f"      在以下字段中包含关键词: {', '.join(details['expected_matches'][file])}")
                    # 显示文件内容片段
                    for field in details['expected_matches'][file]:
                        content = str(self.test_data[file].get(field, ''))
                        print(f"      {field}: {content[:100]}...")
                        
            if extra:
                print("\n  多余的文件:")
                for file in extra:
                    print(f"    - {file}")
                    if file in self.test_data:
                        for field in fields_to_check:
                            content = str(self.test_data[file].get(field, ''))
                            if content:
                                print(f"      {field}: {content[:100]}...")
                                
            # 更新测试状态
            if missing or extra:
                all_tests_passed = False
                print(f"\n  ✗ 关键词 '{keyword}' 测试失败")
                print(f"    - 遗漏了 {len(missing)} 个文件")
                print(f"    - 多返回了 {len(extra)} 个文件")
            else:
                print(f"\n  ✓ 关键词 '{keyword}' 测试通过: 完全匹配 {details['total_found']} 个文件")
                
        # 输出最终结果
        if all_tests_passed:
            print("\n✓ 所有搜索完整性测试通过！")
            print(f"  - 成功测试了 {len(test_words)} 个关键词")
            print("  - 没有发现任何漏项或多余项")
        else:
            failed_keywords = [k for k, v in test_results.items() if v['missing'] or v['extra']]
            self.fail(f"搜索完整性测试失败: {len(failed_keywords)} 个关键词存在问题: {', '.join(failed_keywords)}")

if __name__ == '__main__':
    unittest.main() 